package calendar;

import calendar.messages.*;
import edu.gmu.messages.EndPoint;
import edu.gmu.middleware.RemoteStub;
import edu.gmu.middleware.Message;
import edu.gmu.server.RmiSkeleton;
import java.io.IOException;
import java.util.ArrayList;

public class CalendarSkeleton extends RmiSkeleton implements CallbackInt
{
    private CalendarObj calendar = null;
    private EndPoint endpoint    = null;
    
    /**
     * Creates a new CalendarSkeleton with specified params.
     */
    public CalendarSkeleton(    CalendarObj calendar,
                                EndPoint endpoint,
                                String name )
    {
        super( endpoint.port, endpoint.port, name );
        
        this.endpoint = endpoint;
        this.calendar = calendar;
    }
    
    public EndPoint getEndPoint()
    {
        return this.endpoint;
    }
    
    
    /**
     * Handles a new client connection.
     * @param Socket clientSocket
     */
    public void handleRequests( RemoteStub stub ) throws IOException
    {
        //--------------------------------------------------------------------//
        // Executed in handlerThread
        //--------------------------------------------------------------------//
        stub.register(Topic.USER_REQUEST,            UserRequest.class);
        stub.register(Topic.ISCONNECTED_REQUEST,     IsconnectedRequest.class);
        stub.register(Topic.CLEAR_MEMBERS_REQUEST,   ClearMembersRequest.class);
        stub.register(Topic.SCHEDULE_REQUEST,        ScheduleRequest.class);
        stub.register(Topic.RETRIEVE_REQUEST,        RetrieveRequest.class);
        stub.register(Topic.ALIVE_REQUEST,           AliveRequest.class);
        stub.register(Topic.LOCK_REQUEST,            LockRequest.class);
        stub.register(Topic.UNLOCK_REQUEST,          UnlockRequest.class);
        stub.register(Topic.UPDATE_REQUEST,          UpdateRequest.class);
        stub.register(Topic.NOTIFY_EVENT,            NotifyEvent.class);
        stub.register(Topic.NOTIFY_USER,             NotifyUser.class);
        stub.register(Topic.RECONNECT_CLIENT,        ReconnectRequest.class);
        
        /*
         * Read from clientsocket continusouyly until error or disconnect 
         */
        //boolean disconnect = false;
        while( stopped == false )
        {
            Message message = stub.receive();
            
            if( message instanceof UserRequest )
            {
                UserRequest request = (UserRequest)message;
                
                User user = this.calendar.getUser();
                
                UserResponse result = new UserResponse();
                result.user = user;
                
                stub.send(Topic.USER_RESPONSE, result); 
            }
            else if( message instanceof IsconnectedRequest )
            {
                IsconnectedRequest request = (IsconnectedRequest)message;
                
                boolean connected = this.calendar.isConnected();
                
                IsconnectedResponse result = new IsconnectedResponse();
                result.connected = connected;
                
                stub.send(Topic.ISCONNECTED_RESPONSE, result); 
            }
            else if( message instanceof ClearMembersRequest )
            {
                ClearMembersRequest request = (ClearMembersRequest)message;
                
                this.calendar.clearMembers();
                
                ClearMembersResponse result = new ClearMembersResponse();
                
                stub.send(Topic.CLEAR_MEMBERS_RESPONSE, result); 
            }
            else if( message instanceof ScheduleRequest )
            {
                ScheduleRequest r = (ScheduleRequest)message;
                
                ArrayList users = this.calendar.scheduleEvent(  r.users,
                                                                r.newEvent,
                                                                r.oldEvent,
                                                                r.addToThis );
                
                ScheduleResponse result = new ScheduleResponse();
                result.users = users;
                
                stub.send(Topic.SCHEDULE_RESPONSE, result); 
            }
            else if( message instanceof RetrieveRequest )
            {
                RetrieveRequest r = (RetrieveRequest)message;
                
                ArrayList events = this.calendar.retrieveEvents( r.user,
                                                                r.start,
                                                                r.end );
                
                RetrieveResponse result = new RetrieveResponse();
                result.events = events;
                
                stub.send(Topic.RETRIEVE_RESPONSE, result); 
            }
            else if( message instanceof LockRequest )
            {
                LockRequest request = (LockRequest)message;

                boolean locked = this.calendar.lock();

                LockResponse result = new LockResponse();
                result.locked = locked;

                stub.send(Topic.LOCK_RESPONSE, result);
            }
            else if( message instanceof UnlockRequest )
            {
                UnlockRequest request = (UnlockRequest)message;

                this.calendar.unlock();

                UnlockResponse result = new UnlockResponse();

                stub.send(Topic.UNLOCK_RESPONSE, result);
            }
            else if( message instanceof UpdateRequest )
            {
                UpdateRequest r = (UpdateRequest)message;

                this.calendar.updateEventUsers(  r.users, r.event );

                UpdateResponse result = new UpdateResponse();

                stub.send(Topic.UPDATE_RESPONSE, result);
            }
        }
        stub.stop();
    }
    
    //------------------------------------------------------------------------//
    // Callback stuff
    //------------------------------------------------------------------------//
    public void notifyClientEvent( Event event, boolean appt ) throws IOException
    {
        NotifyEvent eventNotify = new NotifyEvent();
        eventNotify.event = event;
        eventNotify.appt  = appt;
        this.issueCallback(Topic.NOTIFY_EVENT, eventNotify);
    }

    public void notifyClientUser( User user, ArrayList users ) throws IOException
    {
        NotifyUser userNotify = new NotifyUser();
        userNotify.user  = user;
        userNotify.users = users;
        this.issueCallback(Topic.NOTIFY_USER, userNotify);
    }

  public void reconnect() throws IOException {
        ReconnectRequest reconnect = new ReconnectRequest();
        this.issueCallback(Topic.RECONNECT_CLIENT, reconnect);
  }
    //------------------------------------------------------------------------//
    
    

}
